<?php
namespace FastPHP\Library;

/**
 * 分页类
 * 支持多种分页样式：bootstrap、simple、自定义模板
 */
class Paginator
{
    /**
     * 总记录数
     * @var int
     */
    protected $total = 0;
    
    /**
     * 每页记录数
     * @var int
     */
    protected $perPage = 10;
    
    /**
     * 当前页码
     * @var int
     */
    protected $currentPage = 1;
    
    /**
     * 总页数
     * @var int
     */
    protected $totalPages = 0;
    
    /**
     * 分页样式
     * @var string
     */
    protected $style = 'bootstrap';
    
    /**
     * 自定义模板
     * @var string
     */
    protected $template = '';
    
    /**
     * 分页配置
     * @var array
     */
    protected $config = [];
    
    /**
     * 构造函数
     * @param int $total 总记录数
     * @param int $perPage 每页记录数
     * @param int $currentPage 当前页码
     * @param array $config 配置参数
     */
    public function __construct($total, $perPage = 10, $currentPage = 1, $config = [])
    {
        $this->total = (int)$total;
        $this->perPage = (int)$perPage;
        $this->currentPage = (int)$currentPage;
        
        // 获取分页配置
        $this->config = array_merge($this->getDefaultConfig(), $config);
        
        // 计算总页数
        $this->totalPages = $this->calculateTotalPages();
        
        // 验证当前页码
        $this->validateCurrentPage();
    }
    
    /**
     * 获取默认配置
     * @return array
     */
    protected function getDefaultConfig()
    {
        $config = config('app.paginator', []);
        
        return array_merge([
            'style' => 'bootstrap',
            'template' => '',
            'show_total' => true,
            'show_info' => true,
            'show_prev_next' => true,
            'show_first_last' => true,
            'prev_text' => '上一页',
            'next_text' => '下一页',
            'first_text' => '首页',
            'last_text' => '末页',
            'ellipsis' => '...',
            'max_links' => 5,
            'class' => 'pagination',
            'item_class' => 'page-item',
            'link_class' => 'page-link',
            'active_class' => 'active',
            'disabled_class' => 'disabled',
            'info_template' => '显示第 {start} - {end} 条，共 {total} 条记录',
            'total_template' => '共 {total} 条记录',
        ], $config);
    }
    
    /**
     * 计算总页数
     * @return int
     */
    protected function calculateTotalPages()
    {
        if ($this->perPage <= 0) {
            return 0;
        }
        return (int)ceil($this->total / $this->perPage);
    }
    
    /**
     * 验证当前页码
     */
    protected function validateCurrentPage()
    {
        if ($this->currentPage < 1) {
            $this->currentPage = 1;
        }
        if ($this->currentPage > $this->totalPages && $this->totalPages > 0) {
            $this->currentPage = $this->totalPages;
        }
    }
    
    /**
     * 设置分页样式
     * @param string $style
     * @return $this
     */
    public function setStyle($style)
    {
        $this->style = $style;
        return $this;
    }
    
    /**
     * 设置自定义模板
     * @param string $template
     * @return $this
     */
    public function setTemplate($template)
    {
        $this->template = $template;
        return $this;
    }
    
    /**
     * 获取分页信息
     * @return array
     */
    public function getInfo()
    {
        $start = ($this->currentPage - 1) * $this->perPage + 1;
        $end = min($this->currentPage * $this->perPage, $this->total);
        
        return [
            'total' => $this->total,
            'per_page' => $this->perPage,
            'current_page' => $this->currentPage,
            'total_pages' => $this->totalPages,
            'start' => $start,
            'end' => $end,
            'has_prev' => $this->currentPage > 1,
            'has_next' => $this->currentPage < $this->totalPages,
            'prev_page' => $this->currentPage - 1,
            'next_page' => $this->currentPage + 1,
        ];
    }
    
    /**
     * 获取分页链接数组
     * @return array
     */
    public function getLinks()
    {
        $links = [];
        $info = $this->getInfo();
        
        // 首页
        if ($this->config['show_first_last'] && $info['current_page'] > 1) {
            $links[] = [
                'page' => 1,
                'text' => $this->config['first_text'],
                'type' => 'first',
                'active' => false,
                'disabled' => false,
            ];
        }
        
        // 上一页
        if ($this->config['show_prev_next'] && $info['has_prev']) {
            $links[] = [
                'page' => $info['prev_page'],
                'text' => $this->config['prev_text'],
                'type' => 'prev',
                'active' => false,
                'disabled' => false,
            ];
        }
        
        // 页码链接
        $pageLinks = $this->getPageLinks();
        foreach ($pageLinks as $page) {
            $links[] = [
                'page' => $page,
                'text' => $page,
                'type' => 'page',
                'active' => $page == $info['current_page'],
                'disabled' => false,
            ];
        }
        
        // 下一页
        if ($this->config['show_prev_next'] && $info['has_next']) {
            $links[] = [
                'page' => $info['next_page'],
                'text' => $this->config['next_text'],
                'type' => 'next',
                'active' => false,
                'disabled' => false,
            ];
        }
        
        // 末页
        if ($this->config['show_first_last'] && $info['current_page'] < $info['total_pages']) {
            $links[] = [
                'page' => $info['total_pages'],
                'text' => $this->config['last_text'],
                'type' => 'last',
                'active' => false,
                'disabled' => false,
            ];
        }
        
        return $links;
    }
    
    /**
     * 获取页码链接
     * @return array
     */
    protected function getPageLinks()
    {
        $links = [];
        $current = $this->currentPage;
        $total = $this->totalPages;
        $maxLinks = $this->config['max_links'];
        
        if ($total <= $maxLinks) {
            // 总页数小于等于最大链接数，显示所有页码
            for ($i = 1; $i <= $total; $i++) {
                $links[] = $i;
            }
        } else {
            // 计算显示的页码范围
            $half = (int)($maxLinks / 2);
            $start = max(1, $current - $half);
            $end = min($total, $start + $maxLinks - 1);
            
            // 调整起始页
            if ($end - $start + 1 < $maxLinks) {
                $start = max(1, $end - $maxLinks + 1);
            }
            
            // 添加首页省略号
            if ($start > 1) {
                $links[] = 1;
                if ($start > 2) {
                    $links[] = 'ellipsis';
                }
            }
            
            // 添加页码
            for ($i = $start; $i <= $end; $i++) {
                $links[] = $i;
            }
            
            // 添加末页省略号
            if ($end < $total) {
                if ($end < $total - 1) {
                    $links[] = 'ellipsis';
                }
                $links[] = $total;
            }
        }
        
        return $links;
    }
    
    /**
     * 生成分页HTML
     * @param string $url 链接URL模板，支持 {page} 占位符
     * @return string
     */
    public function render($url = '')
    {
        if (empty($this->total)) {
            return '';
        }
        
        if (!empty($this->template)) {
            return $this->renderCustom();
        }
        
        switch ($this->style) {
            case 'simple':
                return $this->renderSimple($url);
            case 'bootstrap':
            default:
                return $this->renderBootstrap($url);
        }
    }
    
    /**
     * 渲染Bootstrap分页
     * @param string $url
     * @return string
     */
    protected function renderBootstrap($url)
    {
        $links = $this->getLinks();
        $info = $this->getInfo();
        
        $html = '<nav aria-label="分页导航">';
        $html .= '<ul class="' . $this->config['class'] . '">';
        
        foreach ($links as $link) {
            $class = $this->config['item_class'];
            
            if ($link['active']) {
                $class .= ' ' . $this->config['active_class'];
            }
            
            if ($link['disabled']) {
                $class .= ' ' . $this->config['disabled_class'];
            }
            
            $html .= '<li class="' . $class . '">';
            
            if ($link['type'] === 'ellipsis') {
                $html .= '<span class="' . $this->config['link_class'] . '">' . $this->config['ellipsis'] . '</span>';
            } else {
                $href = $this->buildUrl($url, $link['page']);
                $html .= '<a class="' . $this->config['link_class'] . '" href="' . $href . '">' . $link['text'] . '</a>';
            }
            
            $html .= '</li>';
        }
        
        $html .= '</ul>';
        
        // 添加分页信息
        if ($this->config['show_info']) {
            $infoText = str_replace(
                ['{start}', '{end}', '{total}'],
                [$info['start'], $info['end'], $info['total']],
                $this->config['info_template']
            );
            $html .= '<div class="pagination-info">' . $infoText . '</div>';
        }
        
        $html .= '</nav>';
        
        return $html;
    }
    
    /**
     * 渲染简单分页
     * @param string $url
     * @return string
     */
    protected function renderSimple($url)
    {
        $links = $this->getLinks();
        $info = $this->getInfo();
        
        $html = '<div class="pagination-simple">';
        
        foreach ($links as $link) {
            if ($link['type'] === 'ellipsis') {
                $html .= '<span>' . $this->config['ellipsis'] . '</span>';
            } else {
                $href = $this->buildUrl($url, $link['page']);
                $class = $link['active'] ? 'current' : '';
                $html .= '<a href="' . $href . '" class="' . $class . '">' . $link['text'] . '</a>';
            }
        }
        
        // 添加分页信息
        if ($this->config['show_info']) {
            $infoText = str_replace(
                ['{start}', '{end}', '{total}'],
                [$info['start'], $info['end'], $info['total']],
                $this->config['info_template']
            );
            $html .= '<span class="pagination-info">' . $infoText . '</span>';
        }
        
        $html .= '</div>';
        
        return $html;
    }
    
    /**
     * 渲染自定义模板
     * @return string
     */
    protected function renderCustom()
    {
        $links = $this->getLinks();
        $info = $this->getInfo();
        
        // 将数据传递给模板
        $data = [
            'links' => $links,
            'info' => $info,
            'config' => $this->config,
        ];
        
        // 这里可以实现自定义模板渲染逻辑
        // 暂时返回简单HTML
        return $this->renderSimple('');
    }
    
    /**
     * 构建URL
     * @param string $url
     * @param int $page
     * @return string
     */
    protected function buildUrl($url, $page)
    {
        if (empty($url)) {
            // 如果没有提供URL模板，使用当前URL
            $url = $_SERVER['REQUEST_URI'];
            $url = preg_replace('/[?&]page=\d+/', '', $url);
            $url .= (strpos($url, '?') !== false ? '&' : '?') . 'page={page}';
        }
        
        return str_replace('{page}', $page, $url);
    }
    
    /**
     * 获取分页数据
     * @return array
     */
    public function getData()
    {
        $info = $this->getInfo();
        $links = $this->getLinks();
        
        return [
            'info' => $info,
            'links' => $links,
            'config' => $this->config,
        ];
    }
    
    /**
     * 获取偏移量
     * @return int
     */
    public function getOffset()
    {
        return ($this->currentPage - 1) * $this->perPage;
    }
    
    /**
     * 获取限制
     * @return int
     */
    public function getLimit()
    {
        return $this->perPage;
    }
    
    /**
     * 静态方法：创建分页实例
     * @param int $total
     * @param int $perPage
     * @param int $currentPage
     * @param array $config
     * @return Paginator
     */
    public static function make($total, $perPage = 10, $currentPage = 1, $config = [])
    {
        return new self($total, $perPage, $currentPage, $config);
    }
} 